package com.example.sirius_swu.myexample.AppsList;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
import android.net.TrafficStats;
import android.text.format.Formatter;
import android.util.Log;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 获取手机应用程序
 * Created by sirius_swu on 2017/6/27.
 */

public class AppInfoService {

    private Context context;
    private PackageManager pm;
    public AppInfoService(Context context) {
        // TODO Auto-generated constructor stub
        this.context = context;
        pm = context.getPackageManager();
    }

    /**
     * 得到手机中所有的应用程序信息
     * @return
     */
    public List<AppInfo> getAppInfos(){
        //创建要返回的集合对象
        List<AppInfo> appInfos = new ArrayList<AppInfo>();
        //获取手机中所有安装的应用集合
        List<ApplicationInfo> applicationInfos = pm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);
        //遍历所有的应用集合
        for(ApplicationInfo info : applicationInfos){

            AppInfo appInfo = new AppInfo();

            // 获取应用程序的图标
            Drawable app_icon = info.loadIcon(pm);
            appInfo.setApp_icon(app_icon);

            // 获取应用的名称
            String app_name = info.loadLabel(pm).toString();
            appInfo.setApp_name(app_name);

            // 获取应用的包名
            String packageName = info.packageName;
            appInfo.setPackagename(packageName);

            // 获取应用的运行时间
            long aUseTime = isThisAppUsedTime(context, info.packageName);
            appInfo.setaUseTime(aUseTime);
            Log.i("aUseTime", String.valueOf(aUseTime));

            // 获取应用的启动次数
            long aLaunchCount = isThisAppUsedCount(context, info.packageName);
            appInfo.setaLaunchCount(aLaunchCount);
            Log.i("aLaunchCount", String.valueOf(aLaunchCount));

            // 获取应用的网络消耗
            getAppTrafficList(context, appInfo);

            try {
                //获取应用的版本号
                PackageInfo packageInfo = pm.getPackageInfo(packageName, 0);
                String app_version = packageInfo.versionName;
                appInfo.setApp_version(app_version);
            } catch (NameNotFoundException e) {
                e.printStackTrace();
            }
            //判断应用程序是否是用户程序
            boolean isUserApp = filterApp(info);
            appInfo.setUserApp(isUserApp);
            appInfos.add(appInfo);
        }
        return appInfos;
    }

    // 判断应用程序是否是用户程序
    public boolean filterApp(ApplicationInfo info) {
        //原来是系统应用，用户手动升级
        if ((info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
            return true;
            //用户自己安装的应用程序
        } else if ((info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
            return true;
        }
        return false;
    }

    // 反射获得应用启动次数
    public final long isThisAppUsedCount(Context context, String packageName) {
//        long aUseTime=0;
        long aLaunchCount=0;
        PackageManager pm = context.getPackageManager();
        try {
            Intent i = pm.getLaunchIntentForPackage(packageName);
            ComponentName aName = i.getComponent();
            Log.i("TAG", aName.toString());

//                        ComponentName aName = new ComponentName(packageName, getActivity(context,packageName));

            // 获得ServiceManager类
            Class<?> ServiceManager = Class
                    .forName("android.os.ServiceManager");

            // 获得ServiceManager的getService方法
            Method getService = ServiceManager.getMethod("getService",
                    java.lang.String.class);

            // 调用getService获取RemoteService
            Object oRemoteService = getService.invoke(null, "usagestats");

            // 获得IUsageStats.Stub类
            Class<?> cStub = Class
                    .forName("com.android.internal.app.IUsageStats$Stub");
            // 获得asInterface方法
            Method asInterface = cStub.getMethod("asInterface", android.os.IBinder.class);
            // 调用asInterface方法获取IUsageStats对象
            Object oIUsageStats = asInterface.invoke(null, oRemoteService);
            // 获得getPkgUsageStats(ComponentName)方法
            Method getPkgUsageStats = oIUsageStats.getClass().getMethod(
                    "getPkgUsageStats", ComponentName.class);
            // 调用getPkgUsageStats 获取PkgUsageStats对象
            Object aStats = getPkgUsageStats.invoke(oIUsageStats, aName);

            // 获得PkgUsageStats类
            Class<?> PkgUsageStats = Class
                    .forName("com.android.internal.os.PkgUsageStats");

            aLaunchCount = PkgUsageStats.getDeclaredField("launchCount")
                    .getInt(aStats);
//            aUseTime = PkgUsageStats.getDeclaredField("usageTime").getLong(aStats);

        } catch (Exception e) {
            Log.e("###", e.toString(), e);
            e.printStackTrace();
        }

//        return aUseTime;
        return aLaunchCount;
    }

    // 反射获得应用运行时间
    public final long isThisAppUsedTime(Context context, String packageName) {
        long aUseTime=0;
//        long aLaunchCount=0;
        PackageManager pm = context.getPackageManager();
        try {
            Intent i = pm.getLaunchIntentForPackage(packageName);
            ComponentName aName = i.getComponent();
            Log.i("TAG", aName.toString());

//            ComponentName aName = new ComponentName(packageName, getActivity(context,packageName));

            // 获得ServiceManager类
            Class<?> ServiceManager = Class
                    .forName("android.os.ServiceManager");

            // 获得ServiceManager的getService方法
            Method getService = ServiceManager.getMethod("getService",
                    java.lang.String.class);

            // 调用getService获取RemoteService
            Object oRemoteService = getService.invoke(null, "usagestats");

            // 获得IUsageStats.Stub类
            Class<?> cStub = Class
                    .forName("com.android.internal.app.IUsageStats$Stub");
            // 获得asInterface方法
            Method asInterface = cStub.getMethod("asInterface",
                    android.os.IBinder.class);
            // 调用asInterface方法获取IUsageStats对象
            Object oIUsageStats = asInterface.invoke(null, oRemoteService);
            // 获得getPkgUsageStats(ComponentName)方法
            Method getPkgUsageStats = oIUsageStats.getClass().getMethod(
                    "getPkgUsageStats", ComponentName.class);
            // 调用getPkgUsageStats 获取PkgUsageStats对象
            Object aStats = getPkgUsageStats.invoke(oIUsageStats, aName);

            // 获得PkgUsageStats类
            Class<?> PkgUsageStats = Class
                    .forName("com.android.internal.os.PkgUsageStats");

//            aLaunchCount = PkgUsageStats.getDeclaredField("launchCount")
//                    .getInt(aStats);
            aUseTime = PkgUsageStats.getDeclaredField("usageTime").getLong(aStats);

        } catch (Exception e) {
            Log.e("###", e.toString(), e);
            e.printStackTrace();
        }

        return aUseTime;
//        return aLaunchCount;
    }

    // 获取应用网络消耗
    public void getAppTrafficList(Context context, AppInfo appInfo){
        //获取所有的安装在手机上的应用软件的信息，并且获取这些软件里面的权限信息
        PackageManager pm=context.getPackageManager();//获取系统应用包管理
        //获取每个包内的androidmanifest.xml信息，它的权限等等
        List<PackageInfo> pinfos=pm.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_PERMISSIONS);
        //遍历每个应用包信息
        for(PackageInfo info:pinfos){
            //请求每个程序包对应的androidManifest.xml里面的权限
            String[] permissions=info.requestedPermissions;
            if(permissions!=null && permissions.length>0){
                //找出需要网络服务的应用程序
                for(String permission : permissions){
                    if("android.permission.INTERNET".equals(permission)){
                        //获取每个应用程序在操作系统内的进程id
                        int uId=info.applicationInfo.uid;
                        //如果返回-1，代表不支持使用该方法，注意必须是2.2以上的
                        long rx=TrafficStats.getUidRxBytes(uId);
                        //如果返回-1，代表不支持使用该方法，注意必须是2.2以上的
                        long tx= TrafficStats.getUidTxBytes(uId);
                        if(rx<0 || tx<0){
                            continue;
                        }else{
//       Toast.makeText(this, info.applicationInfo.loadLabel(pm)+"消耗的流量--"+
//      Formatter.formatFileSize(this, rx+tx), Toast.LENGTH_SHORT);
                            // 获取应用的网络消耗
                            appInfo.setNetCost(Formatter.formatFileSize(context, rx+tx));
                        }
                    }
                }
            }
        }
    }

}
